package com.wydstation.power.properties.excel;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cglib.beans.BeanMap;
import org.springframework.util.ObjectUtils;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.*;

/**
 * api request field, reflect util
 *
 * @author xuxueli 2017-05-26
 */
public final class FieldReflectionUtil {

    private static Logger logger = LoggerFactory.getLogger(FieldReflectionUtil.class);

    private FieldReflectionUtil() {
    }

    public static Byte parseByte(String value) {
        try {
            value = value.replaceAll("　", "");
            return Byte.valueOf(value);
        } catch (NumberFormatException e) {
            throw new RuntimeException("parseByte but input illegal input=" + value, e);
        }
    }

    public static Boolean parseBoolean(String value) {
        value = value.replaceAll("　", "");
        if (Boolean.TRUE.toString().equalsIgnoreCase(value)) {
            return Boolean.TRUE;
        } else if (Boolean.FALSE.toString().equalsIgnoreCase(value)) {
            return Boolean.FALSE;
        } else {
            throw new RuntimeException("parseBoolean but input illegal input=" + value);
        }
    }

    public static Integer parseInt(String value) {
        try {
            value = value.replaceAll("　", "");
            return Integer.valueOf(value);
        } catch (NumberFormatException e) {
            throw new RuntimeException("parseInt but input illegal input=" + value, e);
        }
    }

    public static Short parseShort(String value) {
        try {
            value = value.replaceAll("　", "");
            return Short.valueOf(value);
        } catch (NumberFormatException e) {
            throw new RuntimeException("parseShort but input illegal input=" + value, e);
        }
    }

    public static Long parseLong(String value) {
        try {
            value = value.replaceAll("　", "");
            return Long.valueOf(value);
        } catch (NumberFormatException e) {
            throw new RuntimeException("parseLong but input illegal input=" + value, e);
        }
    }

    public static Float parseFloat(String value) {
        try {
            value = value.replaceAll("　", "");
            return Float.valueOf(value);
        } catch (NumberFormatException e) {
            throw new RuntimeException("parseFloat but input illegal input=" + value, e);
        }
    }

    public static Double parseDouble(String value) {
        try {
            value = value.replaceAll("　", "");
            return Double.valueOf(value);
        } catch (NumberFormatException e) {
            throw new RuntimeException("parseDouble but input illegal input=" + value, e);
        }
    }

    public static Date parseDate(String value, ExcelField excelField) {
        try {
            String datePattern = "yyyy-MM-dd HH:mm:ss";
            if (excelField != null) {
                datePattern = excelField.dateformat();
            }
            SimpleDateFormat dateFormat = new SimpleDateFormat(datePattern);
            return dateFormat.parse(value);
        } catch (ParseException e) {
            throw new RuntimeException("parseDate but input illegal input=" + value, e);
        }
    }

    public static LocalDateTime parseLocalDateTime(String value, ExcelField excelField) {
        try {
            String pattern = "yyyy-MM-dd HH:mm:ss";
            if (excelField != null) {
                pattern = excelField.dateformat();
            } else if (value != null && value.split(" ").length == 1) {
                value = value + " 00:00:00";
            }
            DateTimeFormatter dtf = DateTimeFormatter.ofPattern(pattern);
            return LocalDateTime.parse(value, dtf);
        } catch (DateTimeParseException e) {
            throw new RuntimeException("parseLocalDateTime but input illegal input=" + value, e);
        }
    }

    public static BigDecimal parseBigDecimal(String value, ExcelField excelField) {
        try {
            Double val = parseDouble(value);
            return BigDecimal.valueOf(val);
        } catch (NumberFormatException e) {
            throw new RuntimeException("parseBigDecimal but input illegal input=" + value, e);
        }
    }

    /**
     * 参数解析 （支持：Byte、Boolean、String、Short、Integer、Long、Float、Double、Date）
     *
     * @param field
     * @param value
     * @return
     */
    public static Object parseValue(Field field, String value) {
        Class<?> fieldType = field.getType();

        ExcelField excelField = field.getAnnotation(ExcelField.class);
        if (value == null || value.trim().length() == 0) {
            return null;
        }
        value = value.trim();

        /*
         * if (Byte.class.equals(fieldType) || Byte.TYPE.equals(fieldType)) { return
         * parseByte(value); } else
         */
        if (Boolean.class.equals(fieldType) || Boolean.TYPE.equals(fieldType)) {
            return parseBoolean(value);
        } /*
         * else if (Character.class.equals(fieldType) ||
         * Character.TYPE.equals(fieldType)) { return value.toCharArray()[0]; }
         */ else if (String.class.equals(fieldType)) {
            return value;
        } else if (Short.class.equals(fieldType) || Short.TYPE.equals(fieldType)) {
            return parseShort(value);
        } else if (Integer.class.equals(fieldType) || Integer.TYPE.equals(fieldType)) {
            return parseInt(value);
        } else if (Long.class.equals(fieldType) || Long.TYPE.equals(fieldType)) {
            return parseLong(value);
        } else if (Float.class.equals(fieldType) || Float.TYPE.equals(fieldType)) {
            return parseFloat(value);
        } else if (Double.class.equals(fieldType) || Double.TYPE.equals(fieldType)) {
            return parseDouble(value);
        } else if (Date.class.equals(fieldType)) {
            return parseDate(value, excelField);

        } else if (LocalDateTime.class.equals(fieldType)) {
            return parseLocalDateTime(value, excelField);
        } else if (BigDecimal.class.equals(fieldType)) {
            return parseBigDecimal(value, excelField);
        } else {
            throw new RuntimeException(
                    "request illeagal type, type must be Integer not int Long not long etc, type=" + fieldType);
        }
    }

    /**
     * 参数格式化为String
     *
     * @param field
     * @param value
     * @return
     */
    public static String formatValue(Field field, Object value) {
        Class<?> fieldType = field.getType();

        ExcelField excelField = field.getAnnotation(ExcelField.class);
        if (value == null) {
            return null;
        }

        if (Boolean.class.equals(fieldType) || Boolean.TYPE.equals(fieldType)) {
            return String.valueOf(value);
        } else if (String.class.equals(fieldType)) {
            return String.valueOf(value);
        } else if (Short.class.equals(fieldType) || Short.TYPE.equals(fieldType)) {
            return String.valueOf(value);
        } else if (Integer.class.equals(fieldType) || Integer.TYPE.equals(fieldType)) {
            return String.valueOf(value);
        } else if (Long.class.equals(fieldType) || Long.TYPE.equals(fieldType)) {
            return String.valueOf(value);
        } else if (Float.class.equals(fieldType) || Float.TYPE.equals(fieldType)) {
            return String.valueOf(value);
        } else if (Double.class.equals(fieldType) || Double.TYPE.equals(fieldType)) {
            return String.valueOf(value);
        } else if (Date.class.equals(fieldType)) {
            String datePattern = "yyyy-MM-dd HH:mm:ss";
            if (excelField != null && excelField.dateformat() != null) {
                datePattern = excelField.dateformat();
            }
            SimpleDateFormat dateFormat = new SimpleDateFormat(datePattern);
            return dateFormat.format(value);
        }
        else if (BigDecimal.class.equals(fieldType)) {
            return formatBigDecimal(value);
        } else {
            throw new RuntimeException(
                    "request illeagal type, type must be Integer not int Long not long etc, type=" + fieldType);
        }
    }

    private static String formatBigDecimal(Object value) {

        if (value == null) {
            return "";
        }
        BigDecimal bigDecimal = (BigDecimal) value;

        return bigDecimal.doubleValue() + "";
    }


    /**
     * 获取所有字段,包括基类
     *
     * @param clz
     * @return
     */
    public static List<Field> getParentField(Class<?> clz) {

        List<Field> fieldList = new ArrayList<>();
        while (clz != null) {
            fieldList.addAll(0, Arrays.asList(clz.getDeclaredFields()));
            clz = clz.getSuperclass();
        }
        return fieldList;
    }





    /**
     * 判断一个对象是否为空
     *
     * @param obj
     * @return
     */
    public static Boolean isEmptyObject(Object obj) {
        if (obj == null) {
            return true;
        }
        Map<?, ?> res = BeanMap.create(obj);
        for (Map.Entry<?, ?> item : res.entrySet()) {
            if (item.getKey().toString().equals("serialVersionUID")) {
                continue;
            }
            if (item.getValue() != null && !("null".equals(item.getValue()))) {
                return false;
            }
        }
        return true;
    }

    /**
     * 判断一个对象是否为空
     *
     * @param obj
     * @return
     */
    public static Boolean isEmptyObject(Object obj,String propName) {
        if (obj == null) {
            return true;
        }
        Map<?, ?> res = BeanMap.create(obj);
        for (Map.Entry<?, ?> item : res.entrySet()) {
            if (item.getKey().toString().equals("serialVersionUID")||item.getKey().toString().equals(propName)) {
                continue;
            }
            if (item.getValue() != null && !("null".equals(item.getValue()))) {
                return false;
            }
        }
        return true;
    }

    /**
     * 获取对象指定属性的值
     *
     * @param obj
     * @return
     */
    public static Object getPropertyValue(Object obj, String propName) {
        if (obj == null || ObjectUtils.isEmpty(propName)) {
            return null;
        }

        try {
            Field[] fields = obj.getClass().getDeclaredFields();
            for (int j = 0; j < fields.length; j++) {
                if (propName.equals(fields[j].getName())) {
                    fields[j].setAccessible(true);
                    Object res = fields[j].get(obj);

                    return res;
                }

            }
        } catch (Exception ex) {
            logger.warn("FieldReflectionUtil.getPropertyValue failed", ex);
        }

        return null;
    }



}